package connection;

import gui.Desktop;

import java.awt.Color;
import java.awt.Font;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.prefs.Preferences;

import javax.swing.JTextArea;

import org.apache.log4j.Logger;

import database.MySQLConnection;

/**
 * Trida cte data ze serveru
 * 
 * @author dove
 * 
 */
public class Reader extends Thread {

	private int letter;
	private BufferedReader br;
	private static BufferedWriter bw;
	private JTextArea con = new JTextArea();

	private String username = "";
	private String player;
	private String rating;
	private String password = "";
	private String word = "";

	private String colour;
	private String style;
	private int time;

	private static boolean connect = false;

	private Font f = new Font(Font.MONOSPACED, Font.PLAIN, 9);
	private String line = "";
	private Preferences prefs;
	private String language;
	private ResourceBundle messages;
	private static Logger logger = Logger.getLogger("Log");

	private static HashMap<String, PipedOutputStream> writers;
	private static HashMap<String, PipedInputStream> readers;
	private static List<String> isReading;

	/**
	 * Konstruktor pripojuje pipu k sachovnici
	 * 
	 * @param br
	 * @param bw
	 */
	public Reader(BufferedReader br, BufferedWriter bw) {

		this.br = br;
		Reader.bw = bw;
		con.setRows(20);
		con.setColumns(82);
		con.setFont(f);
		con.setEditable(false);
		con.setBackground(Color.white);

		prefs = Preferences.userRoot();
		language = prefs.get("Language", "en");
		Locale currentLocale = new Locale(language);
		messages = ResourceBundle.getBundle("Lang", currentLocale);

		writers = new HashMap<String, PipedOutputStream>();
		readers = new HashMap<String, PipedInputStream>();
		isReading = new ArrayList<String>();
	}

	/**
	 * Posila prikaz na server
	 * 
	 * @param command
	 *            prikaz
	 */
	public static void sendString(String command) {
		try {
			bw.write(command + "\n");
			bw.flush();
		} catch (IOException e) {
			logger.error("", e);
		}
	}

	/**
	 * Nastavuje posilani informaci do pipy
	 * 
	 * @param pipeName
	 *            jmeno pipy
	 */
	public static void setReading(String pipeName) {
		logger.debug(pipeName);
		isReading.add(pipeName);
	}

	/**
	 * Vraci pipu ze ktere je mozno cist data ze serveru
	 * 
	 * @param pipeName
	 *            pojmenovani pipy
	 * @return pipa ze serveru
	 */
	public static PipedInputStream getReader(String pipeName) {

		writers.put(pipeName, new PipedOutputStream());
		try {
			readers.put(pipeName, new PipedInputStream(writers.get(pipeName)));
		} catch (IOException e) {
			logger.error("", e);
		}
		return readers.get(pipeName);
	}

	/**
	 * Vraci stream umoznujici posilani dat na server
	 * 
	 * @return
	 */
	public static BufferedWriter getWriter() {
		return bw;
	}

	/**
	 * Nastavuje prihlasovaci jmeno
	 * 
	 * @param login
	 *            login
	 */
	public void setUsername(String login) {
		username = login;
	}

	/**
	 * Nastavuje heslo pro prihlaseni
	 * 
	 * @param password
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * Pripojen
	 */
	public static void connect() {
		connect = true;
	}

	/**
	 * Odpojen
	 */
	public static void disConnect() {
		connect = false;
	}

	public void run() {
		while (connect) {
			try {
				letter = br.read();
				for (int x = 0; x < isReading.size(); x++) {
					String pipeName = isReading.get(x);
					if (connect) {
						writers.get(pipeName).write(letter);
					} else {
						return;
					}
				}
			} catch (IOException e) {
				logger.error("", e);
			}

			if (letter != 13) {
				word = word.concat(String.valueOf((char) letter));
				line = line.concat(String.valueOf((char) letter));
			} else {
				if (!line.equals("")) {
					if (!line.substring(0, 1).equals("<")
							&& !line.equals("fics% \n")) {
						con.append(line);
						con.setCaretPosition(con.getDocument().getLength());
					}
				}
				line = "";
			}

			if (word.equals("login: ")) {
				try {
					bw.write(username + "\n");
					bw.flush();
				} catch (IOException e) {
					logger.error("", e);
				}
				if (!MySQLConnection.isPlayer(username)) {
					MySQLConnection.insertPlayer(username);
				}
				if (username.equals("guest")) {
					letter = 0;
					word = "<html><CENTER>";
					while (!String.valueOf((char) letter).equals(":")) {
						try {
							letter = br.read();
						} catch (IOException e1) {
							logger.error("", e1);
						}
						if (letter == 10) {
							word += "</CENTER><br><CENTER>";
						} else {
							word = word.concat(String.valueOf((char) letter));
						}
					}
					Desktop.infoMessage(word + "</CENTER><html>");
					prefs.put("checkDatabase", "false");
					Desktop.disableDatabase();
					try {
						bw.write("\n");
						bw.flush();
					} catch (IOException e) {
						logger.error("", e);
					}
				}
			}

			if (word.equals("{Game ")) {

				while (letter != 13) {
					try {
						letter = br.read();
					} catch (Exception e) {
						logger.error("", e);
					}
					word = word.concat(String.valueOf((char) letter));
				}
				con.append(word);
				con.setCaretPosition(con.getDocument().getLength());

				StringTokenizer parse = new StringTokenizer(word);
				List<String> resultLine = new ArrayList<String>();
				while (parse.hasMoreTokens()) {
					resultLine.add(parse.nextToken());
				}
				String result = resultLine.get(resultLine.size() - 1);
				String resultNotice = "END";
				logger.debug("RESULT LINE:" + word);
				logger.debug("RESULT:" + result);
				String secondPlayer = resultLine.get(4);
				secondPlayer = secondPlayer.substring(0,
						secondPlayer.length() - 1);
				logger.debug("RESULT PLAYER:" + secondPlayer);
				logger.debug("PLAYER:" + player);
				if (!result.equals("*")) {
					if (result.length() > 3) {
						// draw
						MySQLConnection.updateGameResult("Draw");
						MySQLConnection.updateSession("Draw");
						MySQLConnection.updatePlayer("Draw");

						resultNotice = messages.getString("Draw_game");
						logger.debug("RESULT:" + resultNotice);

					} else if (result.substring(2).equals("1")) {
						if (secondPlayer.equals(player)) {
							// lose
							MySQLConnection.updateGameResult("Lost");
							MySQLConnection.updateSession("Lost");
							MySQLConnection.updatePlayer("Won");

							resultNotice = messages.getString("You_lose");
							logger.debug("RESULT:" + resultNotice);
						} else {
							// win
							MySQLConnection.updateGameResult("Won");
							MySQLConnection.updateSession("Won");
							MySQLConnection.updatePlayer("Lost");

							resultNotice = messages.getString("You_win");
							logger.debug("RESULT:" + resultNotice);
						}
					} else if (result.substring(2).equals("0")) {
						if (secondPlayer.equals(player)) {
							// lose
							MySQLConnection.updateGameResult("Won");
							MySQLConnection.updateSession("Won");
							MySQLConnection.updatePlayer("Lost");

							resultNotice = messages.getString("You_win");
							logger.debug("RESULT:" + resultNotice);
						} else {
							// win
							MySQLConnection.updateGameResult("Lost");
							MySQLConnection.updateSession("Lost");
							MySQLConnection.updatePlayer("Won");

							resultNotice = messages.getString("You_lose");
							logger.debug("RESULT:" + resultNotice);
						}
					}
				} else {
					resultNotice = messages.getString("game_aborted");
					MySQLConnection.updateGameResult("Aborted");
					logger.debug("RESULT:" + resultNotice);
				}
				String pom = "";
				try {
					while (true) {
						if ((pom = br.readLine()).length() > 4) {
							if (pom.substring(0, 5).equals("fics%")) {
								break;
							}
						}
						word += "<br>" + pom;
						con.append(pom + "\n");
						con.setCaretPosition(con.getDocument().getLength());
					}
				} catch (IOException e) {
					logger.error("", e);
				}
				Desktop.infoMessage("<html><CENTER><b>" + resultNotice
						+ "</b></CENTER><br/><br/>" + word + "</html>");

				word = "";
				line = "";
			}
			if (word.equals("Game ")) {
				while (letter != 13) {
					try {
						letter = br.read();
					} catch (Exception e) {
						logger.error("", e);
					}
					word = word.concat(String.valueOf((char) letter));
				}
				con.append(word);
				con.setCaretPosition(con.getDocument().getLength());
				if (!word.substring(0, 12).equals("Game On-line")) {
					Desktop.infoMessage(word);
				}
			}
			if (word.equals("Notification: ")) {
				while (letter != 13) {
					try {
						letter = br.read();
					} catch (Exception e) {
						logger.error("", e);
					}
					word = word.concat(String.valueOf((char) letter));
				}
				con.append(word);
				con.setCaretPosition(con.getDocument().getLength());
				Desktop.infoMessage(word);
			}
			if (word.equals("Creating: ")) {
				MySQLConnection.moveNumber = 0;
				while (letter != 10) {
					try {
						letter = br.read();
						for (int x = 0; x < isReading.size(); x++) {
							String pipeName = isReading.get(x);
							writers.get(pipeName).write(letter);
						}
					} catch (IOException e) {
						logger.error("", e);
					}
					if (letter != 13) {
						word = word.concat(String.valueOf((char) letter));
					}
				}
				con.append(word);
				con.setCaretPosition(con.getDocument().getLength());
				Desktop.infoMessage(word);
				StringTokenizer creating = new StringTokenizer(word);

				creating.nextToken();
				player = creating.nextToken();
				rating = creating.nextToken();
				if (rating.equals("(")) {
					rating = creating.nextToken();
				}
				if (!player.equalsIgnoreCase(username)) {
					colour = "Black";
					creating.nextToken();
					rating = creating.nextToken();

					if (rating.equals("(")) {
						rating = creating.nextToken().substring(0, 3);
					} else {
						rating = rating.substring(1, 5);
					}
					creating.nextToken();
					style = creating.nextToken();
					String pom = creating.nextToken();
					time = Integer.valueOf(pom);
					logger.debug("RATING:::" + rating);
					if (!rating.equals("++++")) {
						if (!MySQLConnection.isPlayer(player)) {
							MySQLConnection.insertPlayer(player, Integer
									.valueOf(rating));
						}
					} else {
						if (!MySQLConnection.isPlayer(player)) {
							MySQLConnection.insertPlayer(player);
						}
					}
				} else {
					colour = "White";
					player = creating.nextToken();
					rating = creating.nextToken();
					if (rating.equals("(")) {
						rating = creating.nextToken().substring(0, 3);
					} else {
						rating = rating.substring(1, 5);
					}
					creating.nextToken();
					style = creating.nextToken();
					String pom = creating.nextToken();

					time = Integer.valueOf(pom);
					logger.debug("RATING:::" + rating);

					if (!rating.equals("++++")) {
						MySQLConnection.insertPlayer(player, Integer
								.valueOf(rating));
					} else {
						MySQLConnection.insertPlayer(player);
					}

				}
				MySQLConnection.insertGame(style, time, colour, player);
				logger.debug("Creating KONEC!!!!!!!");

				String prvni = "";
				String druha = "";
				try {
					prvni = br.readLine();
					druha = br.readLine();
				} catch (IOException e) {
					logger.error("", e);
				}
				con.append(prvni);
				con.append(druha);
				con.setCaretPosition(con.getDocument().getLength());
				word = "";
				line = "";
			}

			if (word.equals("password: ")) {
				try {
					bw.write(password + "\n");
					bw.flush();
				} catch (IOException e) {
					logger.error("", e);
				}
			}
			if (word.equals("**** ")) {
				try {
					bw.write("iset seekinfo 1\n");
					bw.write("set seek 0\n");
					bw.flush();
				} catch (IOException e) {
					logger.error("", e);
				}
			}
			if (letter == ' ' || letter == 10) {
				word = "";
			}
		}
	}

	/**
	 * Zjisteni jestli jsem pripojen k serveru
	 * 
	 * @return pripojen nebo nepripojen
	 */
	public static boolean isConnect() {
		return connect;
	}

	/**
	 * Vraci vypisovaci plochu konzole
	 * 
	 * @return plocha konzole do ktere je mozno zapisovat
	 */
	public JTextArea getCon() {
		return con;
	}
}
